package top.waikin.mooc.portal.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;
import top.waikin.mooc.entity.Course;
import top.waikin.mooc.entity.CourseRankTuple;
import top.waikin.mooc.portal.service.CourseService;
import top.waikin.mooc.portal.service.RankCacheService;

import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class RankCacheServiceImpl implements RankCacheService {

    @Autowired
    RedisTemplate<String, Object> redisTemplate;

    @Autowired
    CourseService courseService;

    @Value("${redis.database}")
    private String REDIS_DATABASE;

    @Value("${redis.key.courseDayRank}")
    private String COURSE_DAY_RANK;

    @Value("${redis.key.courseWeekRank}")
    private String COURSE_WEEK_RANK;

    @Override
    public void increaseCourseRank(Integer courseId) {
        String key = REDIS_DATABASE + ":" + COURSE_DAY_RANK + ":" + DateUtil.today();
        redisTemplate.opsForZSet().incrementScore(key, courseId, 1);
    }

    @Override
    public List<CourseRankTuple> getWeekRankCourseList() {
        String key = REDIS_DATABASE + ":" + COURSE_WEEK_RANK + ":" + DateUtil.today();
        Set<ZSetOperations.TypedTuple<Object>> typedTuples = redisTemplate.opsForZSet().reverseRangeWithScores(key, 0, -1);
        if (CollUtil.isEmpty(typedTuples)) {
            // 为空则生成排行
            generateWeekRank();
            typedTuples = redisTemplate.opsForZSet().reverseRangeWithScores(key, 0, -1);
        }
        return typedTuples.stream().map(objectTypedTuple -> new CourseRankTuple().setCourse((Course) objectTypedTuple.getValue()).setScore(objectTypedTuple.getScore())).collect(Collectors.toList());
    }

    public void generateWeekRank() {
        Date today = DateUtil.date();
        // 收集时间从昨天到7天前
        Date end = DateUtil.offsetDay(today, -1);
        DateTime start = DateUtil.offsetDay(today, -7);
        String key = REDIS_DATABASE + ":" + COURSE_WEEK_RANK + ":" + DateUtil.formatDate(today);
        String day_key_prefix = REDIS_DATABASE + ":" + COURSE_DAY_RANK + ":";
        List<String> dayKeyList = DateUtil.rangeToList(start, end, DateField.DAY_OF_WEEK)
                .stream().map(DateUtil::formatDate).map(s -> day_key_prefix + s).collect(Collectors.toList());
        System.out.println(dayKeyList);
        // 获取7天的联合
        Set<ZSetOperations.TypedTuple<Object>> courseIdTypedTuples = redisTemplate.opsForZSet().unionWithScores("", dayKeyList);
        // 再存储前20
        Set<ZSetOperations.TypedTuple<Object>> save = courseIdTypedTuples.stream().sorted().limit(20)
                .map(objectTypedTuple -> ZSetOperations.TypedTuple.of((Object) courseService.getById(objectTypedTuple.getValue().toString()), objectTypedTuple.getScore())).collect(Collectors.toSet());
        redisTemplate.opsForZSet().add(key, save);
    }


}
